package w4156.idog.server;

import java.util.List;

import javax.ejb.ConcurrentAccessException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import w4156.idog.client.TestGWT;
import w4156.idog.exception.AuthenticationException;
import w4156.idog.exception.DBexception;
import w4156.idog.exception.GeneralException;
import w4156.idog.model.Card;
import w4156.idog.model.User;

public class TestGWTImpl extends RemoteServiceServlet implements TestGWT {

	private static final long serialVersionUID = -9093912347919110711L;
	private static TransactionManagerBeanRemote transactionManager;

	private static Context transactionCtx;
	static {
		try {
			transactionCtx = new InitialContext();
		    transactionManager = (TransactionManagerBeanRemote) transactionCtx.lookup("ejb/eBlackjack/TransMgrSLSB");
		} catch (NamingException e) {
			throw new GeneralException(e.getMessage());
		} 
	}
	
	public User authenticate(String username, String password) {
		
//		if (true) return new User();
		User user;

		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession(true);
		
		try {
			user = transactionManager.authenticate(username, password, session.getId());
		} catch (Exception e) {
			session.invalidate();
			throw new AuthenticationException("Authentication failed!");
		}
		
		if (user == null) {
			session.invalidate();
			throw new AuthenticationException("Authentication failed.");
		}
		
		session.setAttribute("USER_ID", user.getObjid());
		session.setMaxInactiveInterval(600);// 10 min 60 * 10
		
		return user;
	}

	@Override
	public Card bid(double money) {
		int id = getUserId();
		if (id > 0)
			return transactionManager.bid(id, money, getSessionId());
		else return null;
	}

	@Override
	public void createUser(User user) {
//		System.out.println("Saving user 1 ..... " + user.getName());

		int userId = getUserId();
		if (userId < 0)
			return;
			
		if (transactionManager.isAdmin(userId, getSessionId())) {

			try {
				System.out.println("Saving user 2 ..... " + user.getName());

				user.setObjid(99999);
				int id = transactionManager.createUser(user, getSessionId());
				System.out.println("Saving user successfully: " + id);
			} catch (Exception e) {
				e.printStackTrace();
				throw new DBexception("Failed to create user");
			}
		}
		else {
			System.out.println("Not authorized user");
			throw new AuthenticationException("Not authorized user");
		}
	}

	@Override
	public void deleteUser(User user) throws AuthenticationException,
			DBexception {
		int userId = getUserId();
		if (userId < 0)
			return;
		try {
			if (transactionManager.isAdmin(userId, getSessionId())) {
				System.out.println("Deleting user " + user.getName());
				transactionManager.deleteUser(user, getSessionId());
			} else {
				System.out.println("Not authorized user");
				throw new AuthenticationException("Not authorized user");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new DBexception("Failed to delete user");
		}
	}

	@Override
	public Card doubledown() throws AuthenticationException {
		int userId = getUserId();
		if (userId < 0)
			return null;
		return transactionManager.doubleDown(userId, getSessionId());
	}

	@Override
	public List<Card> getCardList(int userId) throws AuthenticationException {
//		getUserId();
		return null;
//		return transactionManager.getCardList(userId, getSessionId());
	}

	@Override
	/**
	 * Get userId from session
	 * return list of users
	 */
	public List<User> getUserList() {
//		if (true) return null;
		int id = getUserId();
		if (id < 0)
			return null;
		List<User> userlist = null;
		System.out.println("get User List: key : " + id);
		
		try {
			userlist = transactionManager.getUserList(id, getSessionId());
		} catch (ConcurrentAccessException e) {
			// do nothing
		} catch (RuntimeException e) {
			throw new GeneralException(e.getMessage());
		}
		
		if (userlist != null)
//			throw new GeneralException("List is empty");
			System.out.println("get User List: size : " + userlist.size());
		return userlist;
	}

	@Override
	public Card hit() {
		int userId = getUserId();
		if (userId < 0)
			return null;
		return transactionManager.hit(userId, getSessionId());
	}
	
	@Override
	public void joinTable() throws AuthenticationException {
		boolean flag;
		int id = getUserId();
		if (id < 0)
			return;
		try {
//			System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Join Table: " + id);
			flag = transactionManager.joinTable(id, getSessionId());
				
		} catch (RuntimeException e) {
			throw new GeneralException(e.getMessage());
		}
		
		if (!flag) {
//			System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
			throw new GeneralException("joined table failed");

		}
			
	}

	@Override
	public void logout() {
		System.out.println("User log out ...");
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession(false);
		Integer userId;
		if (session == null)
			throw new AuthenticationException("Session expired!");
		
		userId = (Integer)session.getAttribute("USER_ID");
		transactionManager.logout(userId, getSessionId());
		session.invalidate();
		return;
	}

	@Override
	public void modifyUser(User user) throws AuthenticationException,
			DBexception {
		int userId = getUserId();
		if (userId < 0)
			return;
		if (transactionManager.isAdmin(userId, getSessionId())) {

			try {
//				System.out.println("Modifying user " + user.getName());
				transactionManager.modifyUser(user, getSessionId());
			} catch (Exception e) {
				e.printStackTrace();
				throw new DBexception("Failed to delete user");
			}
		}
		else {
			System.out.println("Not authorized user");
			throw new AuthenticationException("Not authorized user");
		}		
	}

	@Override
	public void setReady() {
		int userId = getUserId();
		if (userId < 0)
			return;
		try {
			transactionManager.setReady(userId, getSessionId());
		} catch (Exception e) {
			e.printStackTrace();
			throw new GeneralException(e.getMessage());
		}
	}

	@Override
	public void stand() {
		int id = getUserId();
		if (id > 0)
			transactionManager.stand(id, getSessionId());
	}
	@Override
	public void surrender() {
		int id = getUserId();
		if (id > 0) {
			transactionManager.logout(id, getSessionId());
			logout();
		}
	}
	
	public String testEBJ() {
		return "hello gwt";
	}

	/**
	 * 
	 * @return the current SessionID
	 */
	private String getSessionId() {
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession(false);
		if (session == null) {
			System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
			System.out.println("Session expired!");
			throw new AuthenticationException("Session expired!");
		}
		
		return session.getId();
	}

	/**
	 * @return the current UserId from the session
	 */
	private int getUserId() {
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession(false);
		Integer userId;
		if (session == null)
			return -1;
		
		try {
			userId = (Integer)session.getAttribute("USER_ID");
		} catch (Exception e) {
			return -1;
//			throw new AuthenticationException(e.getMessage());
		}
		return userId;
	}

}
